import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.util.UUID;


class CheckTagRepositoryService {

    boolean transactional = false

    def currents = []

    def scanDirectory( directory ) {
        def pattern = ~/.*\.tag/
        new File( directory ).eachFileMatch(pattern) {f ->
            log.debug "fichero tag ${f.name} encontrado en repositorio"
            buildTag(f)
        }
    }


    def buildTag( f ){
        def ret = new Alimento()
        f.eachLine{ln ->
            def extract = /([a-zA-Z0-9 ]+)+=([a-zA-Z0-9 \-\.\/\\]+)+/
            def matcher = ( ln =~ extract )
            if (matcher.matches()) {
                matcher.each{cv->
                    if( cv[1] == "file" ){
                        def input = new File(cv[2])
                        if( input.exists() == false){
                            return null
                        }
                        ret.crc32 = calculateCrc32(f)

                        def dest = new ByteArrayOutputStream();
			def out = new ZipOutputStream(new BufferedOutputStream(dest));

			def data = new byte[1024];
			def fi = new FileInputStream(f)
			def origin = new BufferedInputStream(fi, 1024);

			ZipEntry entry = new ZipEntry(input.absolutePath);
			out.putNextEntry(entry);
			int count;
			long sum = 0;
			while ((count = origin.read(data, 0, 1024)) != -1) {
                            out.write(data, 0, count);
                            sum += count;
			}
			origin.close();
			out.close();
			dest.close();

                        ret.content = dest.toByteArray()
                        UUID idOne = UUID.randomUUID();
                        ret.nombre = f.name
                        ret.uuid = idOne.toString()
                        log.debug "asignado ${ret.uuid} a ${ret.nombre}"
                    }else{
                        def criteria = Atributo.createCriteria()
                        def result = criteria.list{
                            clave{
                                eq("nombre",cv[1])
                            }
                            eq("valor",cv[2])
                        }
                        result.each{
                            ret.addToAtributos(it)
                        }
                    }
                }
            }
        }
        if( ret.validate() ){
            Alimento.withTransaction{
                def criteria = Pez.createCriteria()
                def results = criteria.list{
                    for( Atributo a : ret.atributos ){
                        atributos{
                            clave{
                                eq("nombre",a.clave.nombre)
                            }
                            eq("valor",a.valor)
                        }
                    }
                }.each{
                    def detalle = new DetalleAlimento(pez:it,alimento:ret)
                    ret.addToDetalles(detalle)
                }

                if(!ret.save()){
                    ret.errors.each{
                        println it
                    }
                }
                f.delete()
            }
            return ret
        }else{
            log.debug "Error creando alimento para peces:"
            ret.errors.each{
                println it
            }
        }
        return null
    }

    long calculateCrc32(file)  {
        FileInputStream fileInput = new FileInputStream(file)
        Adler32 inChecker = new Adler32();
        CheckedInputStream input = new CheckedInputStream(fileInput, inChecker);
        int c;
        while ((c = input.read()) != -1);
        long ret = input.getChecksum().getValue();
        return ret;
    }



}
